//
// Created by Administrator on 2025-07-24.
//

#include "ProtobufBinaryManager.h"

// ProtobufBinaryManager.cpp

#include "ProtobufBinaryManager.h"
#include "/proto/Person.pb.h"
#include <iostream>
#include <cstring>

ProtobufBinaryManager::ProtobufBinaryManager() {}

bool ProtobufBinaryManager::serializeToBuffer(uint8_t* buffer, uint32_t& totalSize)
{
    totalSize = 0;
    binaryMap.clear();

    for (uint32_t type = 1; type < BINARY_VAILD_MAX; ++type)
    {
        std::string serialized;
        bool success = false;

        if (type == ADDRESS)
            success = serializeAddress(serialized);
        else if (type == PERSON)
            success = serializePerson(serialized);

        if (!success) continue;

        std::memcpy(buffer + totalSize, serialized.data(), serialized.size());
        binaryMap[type] = serialized;
        totalSize += serialized.size();
    }

    return true;
}

bool ProtobufBinaryManager::deserializeFromBuffer(const uint8_t* buffer, uint32_t totalSize)
{
    uint32_t offset = 0;
    for (const auto& kv : binaryMap)
    {
        uint32_t type = kv.first;
        const std::string& serialized = kv.second;

        std::string data(reinterpret_cast<const char*>(buffer + offset), serialized.size());
        if (type == ADDRESS)
            deserializeAddress(data);
        else if (type == PERSON)
            deserializePerson(data);

        offset += serialized.size();
        if (offset > totalSize) break;
    }

    return true;
}

bool ProtobufBinaryManager::serializeAddress(std::string& out)
{
    protobuf::serialize::Address proto;
    proto.set_num(123);
    proto.set_addr("127.0.0.1");
    return proto.SerializeToString(&out);
}

bool ProtobufBinaryManager::serializePerson(std::string& out)
{
    protobuf::serialize::Person proto;
    proto.set_id(456);
    proto.set_sex("male");
    proto.set_age(30);
    return proto.SerializeToString(&out);
}

void ProtobufBinaryManager::deserializeAddress(const std::string& data)
{
    protobuf::serialize::Address proto;
    if (proto.ParseFromString(data))
    {
        std::cout << "Address => num: " << proto.num() << ", addr: " << proto.addr() << std::endl;
    }
}

void ProtobufBinaryManager::deserializePerson(const std::string& data)
{
    protobuf::serialize::Person proto;
    if (proto.ParseFromString(data))
    {
        std::cout << "Person => id: " << proto.id()
                  << ", sex: " << proto.sex()
                  << ", age: " << proto.age() << std::endl;
    }
}
